package org.gap.wizards.world;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import org.gap.wizards.Drawable;
import org.gap.wizards.utils.Persistence;
import org.gap.wizards.views.ViewPlatform;
import org.gap.wizards.views.ViewPlatform.Color;

public class Dungeon extends CommonLocation implements Location {
	private List<Path> paths;

	public Dungeon() {
		paths = new ArrayList<Path>();
	}

	@Override
	public void move(Movement move) {
		tryMove(move.adjustLocation(pc.getLocation()));
	}
	
	@Override
	public boolean isBlocked(Point point) {
		for (Path each : paths) {
			if (each.isOnPath(point)) {
				return false;
			}
		}
		return super.isBlocked(point) || !insideBuilding(point);
	}
	
	private boolean insideBuilding(Point moveTo) {
		for (ClosedSpace each : buildings) {
			if (each.contains(moveTo)) {
				return true;
			}
		}
		return false;
	}

	@Override
	protected void drawPermanentFixtures(ViewPlatform console) {
		for (Path each : paths) {
			each.draw(console);
		}
		super.drawPermanentFixtures(console);
	}

	@Override
	public void persist(Persistence persistence) {
		super.persist(persistence);
	}

	@Override
	public void load(Persistence persistence) {
		super.load(persistence);
	}

	public void addRoom(int x, int y, int width, int height, Point door) {
		addClosedSpace(x, y, width, height, door);
	}

	@Override
	protected boolean shouldDraw(Drawable drawable) {
		Point point = new Point(drawable.getX(), drawable.getY());
		for (ClosedSpace each : buildings) {
			if (each.contains(getCharacterLocation()) && each.contains(point)) { return true; }
		}
		for (Path each : paths) {
			if (each.isOnPath(new Point(drawable.getX(), drawable.getY())) && each.isOnPath(getCharacterLocation())) {
				return true;
			}
		}
		return false;
	}

	public void addPath(Point from, Point to) {
		paths.add(new Path(from, to));
	}

	static class Path implements Drawable {
		private final Point from;
		private final Point to;

		public Path(Point from, Point to) {
			this.from = from;
			this.to = to;
		}

		public boolean isOnPath(Point moveTo) {
			if (from.x == to.x) {
				for (int y = from.y; y <= to.y; y++) {
					if (new Point(from.x, y).equals(moveTo)) {
						return true;
					}
				}
			}
			if (from.y == to.y) {
				for (int x = from.x; x <= to.x; x++) {
					if (new Point(x, from.y).equals(moveTo)) {
						return true;
					}
				}
			}
			return false;
		}

		@Override
		public void draw(ViewPlatform console) {
			if (from.x == to.x) {
				for (int y = from.y; y <= to.y; y++) {
					console.print(from.x, y, Color.GRAY, (char)8362);
				}
			}
			if (from.y == to.y) {
				for (int x = from.x; x <= to.x; x++) {
					console.print(x, from.y, Color.GRAY, (char)8362);
				}
			}
		}

		@Override
		public int getX() {
			throw new RuntimeException("should not be called");
		}

		@Override
		public int getY() {
			throw new RuntimeException("should not be called");
		}

	}
}
